/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.lestr.genver.reflection;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author PIBONNIN
 */
public class ProxyFactory {


    public Class<?> constructProxy(Class<?> proxiedClass, Class<?> clientClass, String clientFieldName, InvocationWriter invocationWriter) {

        String proxySource = "using System;\n";
        proxySource = proxySource + "public class " + proxiedClass.getName() + "Proxy" + (proxiedClass.isInterface() ? " implements " : " extends ") + proxiedClass.getName() + " {\n";

        proxySource = proxySource + "  public " + clientClass.getName() + " " + clientFieldName + ";\n";

        for(Method method : proxiedClass.getMethods())
            if(!Modifier.isStatic(method.getModifiers()))
            {

                String returnType = method.getReturnType() == void.class ? "void" : method.getReturnType().getName();

                proxySource = proxySource + "  public " +  returnType + " " + method.getName() + "(";

                Class<?>[] parameterInfos = method.getParameterTypes();

                for(int i = 0; i <= parameterInfos.length - 1 ; i = i + 1)
                {

                        if(i > 0) proxySource = proxySource + ", ";
                        proxySource = proxySource + parameterInfos[i].getName() + " ";
                        proxySource = proxySource + parameterInfos[i].getSimpleName().toLowerCase();

                }

                proxySource = proxySource + ") {\n";

                proxySource = proxySource + "     object[] astenn_args = new object[]{";
                for(int i = 0; i <= parameterInfos.length - 1 ; i = i + 1)
                        proxySource = proxySource + (i > 0 ? ", " : "") + parameterInfos[i].getSimpleName().toLowerCase();
                proxySource = proxySource + "     };\n";

                proxySource = proxySource + "     ";

                if(method.getReturnType() != void.class)
                        proxySource = proxySource + "return (" + returnType + ")";

                proxySource = proxySource + invocationWriter.writeInvocation(proxiedClass, method, "astenn_args");

                proxySource = proxySource + "  }\n\n";

            }

        proxySource = proxySource + "}\n";

        com.sun.tools.javac.Main.compile(new String[]{ proxySource });

        try {
            return Class.forName(proxiedClass.getName() + "Proxy");
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(ProxyFactory.class.getName()).log(Level.SEVERE, null, ex);
        }

        return null;

    }// END Method ConstructProxy


    public static interface InvocationWriter {


        String writeInvocation(Class<?> proxiedClass, Method proxiedMethod, String argsVariableName);


    }// END Interface Invoker


}// END Class ProxyFactory
